{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Merge Sort\n",
    "\n",
    "Code examples from [Think Complexity, 2nd edition](http://greenteapress.com/wp/complexity2), Appendix A\n",
    "\n",
    "Copyright 2017 Allen Downey, [MIT License](http://opensource.org/licenses/MIT)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from __future__ import print_function, division\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "import os\n",
    "import string\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "import thinkplot\n",
    "\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Empirical order of growth\n",
    "\n",
    "Sometimes we can figure out what order of growth a function belongs to by running it with a range of problem sizes and measuring the run time.\n",
    "\n",
    "To measure runtimes, we'll use `etime`, which uses `os.times` to compute the total time used by a process, including \"user time\" and \"system time\".  User time is time spent running your code; system time is time spent running operating system code on your behalf."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def etime():\n",
    "    \"\"\"Measures user and system time this process has used.\n",
    "\n",
    "    Returns the sum of user and system time.\"\"\"\n",
    "    user, sys, chuser, chsys, real = os.times()\n",
    "    return user+sys"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`time_func` takes a function object and a problem size, `n`, runs the function, and returns the elapsed time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def time_func(func, n):\n",
    "    \"\"\"Run a function and return the elapsed time.\n",
    "    \n",
    "    func: function\n",
    "    n: problem size\n",
    "    \n",
    "    returns: user+sys time in seconds\n",
    "    \"\"\"\n",
    "    start = etime()\n",
    "    func(n)\n",
    "    end = etime()\n",
    "    elapsed = end - start\n",
    "    return elapsed"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`run_timing_test` takes a function, runs it with a range of problem sizes, and returns two lists: problem sizes and times."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def run_timing_test(func, max_time=1):\n",
    "    \"\"\"Tests the given function with a range of values for n.\n",
    "    \n",
    "    func: function object\n",
    "\n",
    "    returns: list of ns and a list of run times.\n",
    "    \"\"\"\n",
    "    ns = []\n",
    "    ts = []\n",
    "    for i in range(6, 28):\n",
    "        n = 2**i\n",
    "        t = time_func(func, n)\n",
    "        print(n, t)\n",
    "        if t > 0:\n",
    "            ns.append(n)\n",
    "            ts.append(t)\n",
    "        if t > max_time:\n",
    "            break\n",
    "\n",
    "    return ns, ts"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`fit` takes the lists of ns and ts and fits it with a curve of the form `a * n**exp`, where `exp` is a given exponent and `a` is chosen so that the line goes through a particular point in the sequence, usually the last. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def fit(ns, ts, exp=1.0, index=-1):\n",
    "    \"\"\"Fits a curve with the given exponent.\n",
    "    \n",
    "    ns: sequence of problem sizes\n",
    "    ts: sequence of times\n",
    "    exp: exponent of the fitted curve\n",
    "    index: index of the element the fitted line should go through\n",
    "    \n",
    "    returns: sequence of fitted times\n",
    "\n",
    "    \n",
    "    \"\"\"\n",
    "    # Use the element with the given index as a reference point, \n",
    "    # and scale all other points accordingly.\n",
    "    nref = ns[index]\n",
    "    tref = ts[index]\n",
    "\n",
    "    tfit = []\n",
    "    for n in ns:\n",
    "        ratio = n / nref\n",
    "        t = ratio**exp * tref\n",
    "        tfit.append(t)\n",
    "\n",
    "    return tfit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`plot_timing_test` plots the results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def plot_timing_test(ns, ts, label='', color='blue', exp=1.0, scale='log'):\n",
    "    \"\"\"Plots data and a fitted curve.\n",
    "\n",
    "    ns: sequence of n (problem size)\n",
    "    ts: sequence of t (run time)\n",
    "    label: string label for the data curve\n",
    "    color: string color for the data curve\n",
    "    exp: exponent (slope) for the fitted curve\n",
    "    \"\"\"\n",
    "    tfit = fit(ns, ts, exp)\n",
    "    plt.plot(ns, tfit, color='0.7', linewidth=2, linestyle='dashed')\n",
    "    plt.plot(ns, ts, 's-', label=label, color=color, alpha=0.5, linewidth=3)\n",
    "    plt.xlabel('Problem size (n)')\n",
    "    plt.ylabel('Runtime (seconds)')\n",
    "    plt.xscale(scale)\n",
    "    plt.yscale(scale)\n",
    "    plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For small values of `n`, the runtime is so short that we're probably not getting an accurate measurement of just the operation we're interested in.  But as `n` increases, runtime seems to converge to a line with slope 1.  \n",
    "\n",
    "That suggests that performing append `n` times is linear, which suggests that a single append is constant time.  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comparing sort algorithms\n",
    "\n",
    "NumPy provides implementations of three sorting algorithms, quicksort, mergesort, and heapsort.\n",
    "\n",
    "Read about each of these algorithms to see what order of growth they belong to.\n",
    "\n",
    "Now let's see if we can characterize their asymptotic behavior.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64 0.0\n",
      "128 0.0\n",
      "256 0.0\n",
      "512 0.0\n",
      "1024 0.0\n",
      "2048 0.0\n",
      "4096 0.0\n",
      "8192 0.0\n",
      "16384 0.0\n",
      "32768 0.009999999999999787\n",
      "65536 0.010000000000000231\n",
      "131072 0.029999999999999805\n",
      "262144 0.040000000000000036\n",
      "524288 0.06999999999999984\n",
      "1048576 0.1299999999999999\n",
      "2097152 0.25000000000000044\n",
      "4194304 0.7599999999999998\n",
      "8388608 1.1599999999999993\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nB8T0R2fDOD0AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f5e7a14f0f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def test_quicksort(n):\n",
    "    xs = np.random.normal(size=n)\n",
    "    xs.sort(kind='quicksort')\n",
    "\n",
    "ns, ts = run_timing_test(test_quicksort)\n",
    "plot_timing_test(ns, ts, 'test_quicksort', exp=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Quicksort is hard to distinguish from linear, up to about 10 million elements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64 0.0\n",
      "128 0.0\n",
      "256 0.0\n",
      "512 0.0\n",
      "1024 0.0\n",
      "2048 0.0\n",
      "4096 0.0\n",
      "8192 0.0\n",
      "16384 0.009999999999999787\n",
      "32768 0.009999999999999787\n",
      "65536 0.0\n",
      "131072 0.019999999999999574\n",
      "262144 0.03000000000000025\n",
      "524288 0.07000000000000028\n",
      "1048576 0.1299999999999999\n",
      "2097152 0.29000000000000004\n",
      "4194304 0.6399999999999997\n",
      "8388608 1.370000000000001\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nA/SzEkX0mt/3AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f5e77996e80>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def test_mergesort(n):\n",
    "    xs = np.random.normal(size=n)\n",
    "    xs.sort(kind='mergesort')\n",
    "\n",
    "ns, ts = run_timing_test(test_mergesort)\n",
    "plot_timing_test(ns, ts, 'test_mergesort', exp=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Merge sort is similar, maybe with some upward curvature."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64 0.0\n",
      "128 0.0\n",
      "256 0.0\n",
      "512 0.0\n",
      "1024 0.0\n",
      "2048 0.0\n",
      "4096 0.0\n",
      "8192 0.009999999999999787\n",
      "16384 0.0\n",
      "32768 0.009999999999999787\n",
      "65536 0.010000000000001563\n",
      "131072 0.02999999999999936\n",
      "262144 0.03999999999999915\n",
      "524288 0.08000000000000007\n",
      "1048576 0.120000000000001\n",
      "2097152 0.25\n",
      "4194304 0.6500000000000004\n",
      "8388608 1.299999999999999\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f5e776c75c0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def test_heapsort(n):\n",
    "    xs = np.random.normal(size=n)\n",
    "    xs.sort(kind='heapsort')\n",
    "\n",
    "ns, ts = run_timing_test(test_quicksort)\n",
    "plot_timing_test(ns, ts, 'test_heapsort', exp=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The three methods are effectively linear over this range of problem sizes.\n",
    "\n",
    "And their run times are about the same, with quicksort being the fastest, despite being the one with the worst asympotic performance in the worst case."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Implementing Merge Sort\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def merge_sort_norec(xs):\n",
    "    N = len(xs)\n",
    "    left = xs[:N//2]\n",
    "    right = xs[N//2:]\n",
    "    \n",
    "    left.sort()\n",
    "    right.sort()\n",
    "    \n",
    "    return merge(left, right)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This version breaks the array in half, uses `np.sort` to sort the two halves, then uses merge to put the halves together.\n",
    "\n",
    "**Exercise:** Write a function called `merge` that takes two sorted NumPy arrays, `left` and `right`, and returns a new array that contains all elements from `left` and `right`, sorted.  (where \"sorted\" means in ascending order, or non-decreasing, to be more precise).\n",
    "\n",
    "Note: this function is not hard to write, but it is notoriously difficult to get all of the edge cases right without making the function unreadable.  Take it as a challenge to write a version that is correct, concise, and readable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Solution\n",
    "\n",
    "def merge(left, right):\n",
    "    def dump(array, index):\n",
    "        res[k:] = array[index:]\n",
    "        return res\n",
    "\n",
    "    n, m = len(left), len(right)\n",
    "    res = np.empty(n + m)\n",
    "    i = 0\n",
    "    j = 0\n",
    "    \n",
    "    for k in range(len(res)):\n",
    "        if i == n:\n",
    "            return dump(right, j)\n",
    "        if j == m:\n",
    "            return dump(left, i)\n",
    "        \n",
    "        if left[i] < right[j]:\n",
    "            res[k], i = left[i], i+1\n",
    "        else:\n",
    "            res[k], j = right[j], j+1\n",
    "            \n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xs = np.random.random(10)\n",
    "ys = np.random.random(10)\n",
    "xs.sort()\n",
    "ys.sort()\n",
    "res = merge(xs, ys)\n",
    "all(sorted(res) == res)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise:**  Starting with `merge_sort_norec`, write a function called `merge_sort_rec` that's fully recursive; that is, instead of using `numpy.sort` to compute the DFTs of the halves, it should use `merge_sort_rec`.  Of course, you will need a base case to avoid an infinite recursion.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Solution\n",
    "\n",
    "def merge_sort_rec(xs):\n",
    "    N = len(xs)\n",
    "    if N < 2:\n",
    "        return xs\n",
    "    \n",
    "    left = merge_sort_rec(xs[:N//2])\n",
    "    right = merge_sort_rec(xs[N//2:])\n",
    "    \n",
    "    return merge(left, right)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Test your method by running the code in the next cell, then use `test_merge_sort_rec`, below, to check the performance of your function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xs = np.random.random(10)\n",
    "\n",
    "res = merge_sort_rec(xs)\n",
    "all(sorted(res) == res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64 0.0\n",
      "128 0.0\n",
      "256 0.009999999999999787\n",
      "512 0.009999999999999787\n",
      "1024 0.02999999999999936\n",
      "2048 0.05000000000000071\n",
      "4096 0.07000000000000028\n",
      "8192 0.1999999999999993\n",
      "16384 0.21000000000000085\n",
      "32768 0.5599999999999987\n",
      "65536 1.070000000000002\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nGhxKKaX88v8DvaNIIDlJ7I8AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f5e772d9748>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def test_merge_sort_rec(n):\n",
    "    xs = np.random.normal(size=n)\n",
    "    spectrum = merge_sort_rec(xs)\n",
    "\n",
    "ns, ts = run_timing_test(test_merge_sort_rec)\n",
    "plot_timing_test(ns, ts, 'test_merge_sort_rec', exp=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If things go according to plan, your implementation of merge sort should be close to linear, or a little steeper."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
